package org.wk.core.web.unitofwork;

import java.util.concurrent.atomic.AtomicInteger;

import org.wk.core.common.unitofwork.Processor;
import org.wk.core.common.unitofwork.Processor.Either;



/**
 * 
 * @ClassName	: UnitOfWork
 * @Package		：org.wk.core.web.unitofwork
 * @Author df.w 
 * @Create Time	：2018年5月2日 上午10:11:03
 * @Description	:
 */
public class UnitOfWork {
	private AtomicInteger repeatExecuteCount = new AtomicInteger(0);
	private Processor processor;

	public static class Builder {
		private int repeatExecuteCount = 0;
		private Processor processor;

		public Builder(Processor processor) {
			this.processor = processor;
		}

		public Builder shouldRepeatExecuteCount(int count) {
			this.repeatExecuteCount = count;
			return this;
		}

		public UnitOfWork build() {
			return new UnitOfWork(this);
		}
	}

	public UnitOfWork(Builder builder) {
		this.repeatExecuteCount = new AtomicInteger(builder.repeatExecuteCount);
		this.processor = builder.processor;
	}

	public void execute() {
		Either<? extends Exception, Boolean> executeResult = processor.execute();
		// 判断是否执行失败
		if (executeResult.isLeft()) {
			UnitOfWorkException unitOfWorkException = new UnitOfWorkException(executeResult.left());
			Either<? extends Exception,Boolean> executeProcessException = processor.executeProcessException(executeResult.left());
			if(executeProcessException.isLeft()){
				Exception exception = executeProcessException.left();
				unitOfWorkException.setRollbackException(exception);
				throw unitOfWorkException;
			}
			executeTask(executeResult,unitOfWorkException);
		}
	}
	private void executeTask(Either<? extends Exception, Boolean> execute,UnitOfWorkException unitOfWorkException){
		while (repeatExecuteCount.get() > 0) {
			execute = processor.execute();
			if (execute.isLeft()) {
				Exception exception = execute.left();
				unitOfWorkException.addProcessException(exception);
				Either<? extends Exception,Boolean> executeProcessException = processor.executeProcessException(exception);
				if(executeProcessException.isLeft()){
					Exception executeRollBackExceptionResult = executeProcessException.left();
					unitOfWorkException.setRollbackException(executeRollBackExceptionResult);
					throw unitOfWorkException;
				}
				repeatExecuteCount.decrementAndGet();
			}else{
				return ;
			}
		}
	}
}
